home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994 February: Tool Chest / Dev.CD Feb 94.toast / New System Software Extensions / QuickDraw™ GX v1.0ß2 / Sample Code / Typography Samples / CircularLayoutSample ƒ / CircularLayoutSample.c next >
Encoding:
C/C++ Source or Header  |  1993-09-10  |  10.5 KB  |  402 lines  |  [TEXT/MPS ]

  1. /*
  2.     Circluar Layout Sample Program
  3.     By Eric Mader,
  4.     After Mike Fairman, Oliver Steele et. al.
  5.     
  6.     1.0B2 (09/09/93, MD) -- now allocates its own graphics client of 1 MB instead
  7.                             of accepting the default 600K client.  We were running
  8.                             out of memory.
  9. */
  10.  
  11. /* Copyright ©1989, 1990, 1991 Apple Computer, Inc.  All rights reserved. */
  12.  
  13. #ifndef THINK_C
  14. #include <Quickdraw.h>
  15. #include <Fonts.h>
  16. #include <Windows.h>
  17. #include <Dialogs.h>
  18. #include <Events.h>
  19. #include <Memory.h>
  20. #include <Menus.h>
  21. #include <String.h>
  22. #include <Desk.h>
  23. #include <Script.h>
  24. #include <ToolUtils.h>
  25. #define thePort qd.thePort
  26. #define screenBits qd.screenBits
  27. #endif
  28.  
  29. #include "graphics libraries.h"
  30. #include "qd library.h"
  31. #include "graphics debugging.h"
  32. #include "graphics routines.h"
  33. #include "graphics toolbox.h"
  34.  
  35. #include "layout types.h"
  36. #include "layout routines.h"
  37. #include "layout library.h"
  38. #include "layout feature constants.h"
  39.  
  40. /* This macro is useful for constructing fixed values */
  41. #define f(a,b) (((fixed) (a) << 16) + (b))
  42.  
  43. /* various menu and dialog things */
  44. enum {aboutDLOG = 128, appleMenuID = 128, fileMenuID, editMenuID}; /* resource ID's */
  45.  
  46. enum {okButton = 1, showsItem, authorItem};
  47.  
  48. enum {
  49.     /* Apple Menu */
  50.     aboutCommand = 1,
  51.     
  52.     /* File Menu */
  53.     quitCommand = 1,
  54.     
  55.     /* Edit Menu */
  56.     undoCommand = 1,
  57.     cutCommand,
  58.     copyCommand,
  59.     pasteCommand,
  60.     clearCommand};
  61.  
  62. WindowPtr myWindow, whichWindow;
  63. gxViewPort myPort;
  64. Rect qdWindowRect;
  65. Rect growRect = {40, 40, 32767, 32767};
  66. Rect bigRect = {-32768, -32768, 32767, 32767};
  67. gxRectangle windowRect;
  68.  
  69. MenuHandle appleMenu, fileMenu, editMenu;
  70. Boolean done = false;
  71.  
  72. gxColor colorWhite = xRGB (0xFFFF, 0xFFFF, 0xFFFF);    /* white */
  73. gxColor hsvInitial = xHSV (0, 0xFFFF, 0xFFFF); /* red */
  74.  
  75. static void ShowAboutBox ()
  76. {    GrafPtr savePort;
  77.     DialogPtr theDialog;
  78.     short itemType;
  79.     Handle itemHdl;
  80.     Rect itemRect;
  81.     short itemHit;
  82.  
  83.     GetPort(&savePort);
  84.     theDialog = GetNewDialog(aboutDLOG, nil, (WindowPtr) -1);
  85.     SetPort(theDialog);
  86.  
  87.     GetDItem(theDialog, authorItem, &itemType, &itemHdl, &itemRect);
  88.     SetIText(itemHdl, (StringPtr) "\pRice Dream");
  89.     GetDItem(theDialog, showsItem, &itemType, &itemHdl, &itemRect);
  90.     SetIText(itemHdl, (StringPtr) "\pText in a circle");
  91.  
  92.     do {
  93.         ModalDialog(nil, &itemHit);
  94.     } while (itemHit != okButton);
  95.  
  96.     CloseDialog(theDialog);
  97.  
  98.     SetPort(savePort);
  99. }
  100.  
  101. static void SetupMenus ()
  102. {
  103.     InsertMenu (appleMenu = GetMenu (appleMenuID), 0);
  104.     AddResMenu (appleMenu, (ResType) 'DRVR');
  105.     InsertMenu (fileMenu = GetMenu (fileMenuID), 0);
  106.     InsertMenu (editMenu = GetMenu (editMenuID), 0);
  107.     DrawMenuBar ();
  108. }
  109.  
  110. static void DoMenuCommand (long mResult)
  111. {    short theItem = LoWord (mResult), theMenuID = HiWord (mResult);
  112.     GrafPtr savePort;
  113.     Str255 daName;
  114.     
  115.     switch (theMenuID) {
  116.         case appleMenuID:
  117.             if (theItem == aboutCommand) ShowAboutBox ();
  118.             else
  119.             {    GetItem (appleMenu, theItem, daName);
  120.                 GetPort (&savePort);
  121.                 (void) OpenDeskAcc (daName);
  122.                 SetPort (savePort);
  123.             }
  124.         break;
  125.             
  126.         case fileMenuID:
  127.             if (theItem == quitCommand) done = true;
  128.         break;
  129.             
  130.         case editMenuID:
  131.         break;
  132.     }
  133.     
  134.     HiliteMenu (0);
  135. }
  136.  
  137. static short StrLength(char *s)
  138. {short len;
  139.  
  140.     for (len = 0; *s++ != 0; len++) ;
  141.     return len;
  142. }
  143.  
  144. void main()
  145. {    EventRecord theEvent;
  146.     gxDashRecord d;
  147.     gxColor shapeColor;
  148.     commonColor kanjiColor = apple_green;
  149.     gxRectangle bounds, r;
  150.     gxShape layout, oval, whiteOut, eraseOval, kanji;
  151.     gxRunControls controls;
  152.     gxLayoutOptions gxLayoutOptions;
  153.     char *textRuns[3];
  154.     gxStyle textStyles[3];
  155.     short textLengths[3], totalLength, level0 = 0;
  156.     char *text1  = "Aetna ";
  157.                                               /* The following is "Arabic Macintosh" in Arabic: */
  158.                                               /* meem, alif, kaf,  noon, tah,  wau,  shin, */
  159.                                               /* <sp>, alif, lam,  ein,  reh,  beh,  yeh */
  160.     static char text2[] =  {0xE5, 0xC7, 0xE3, 0xE6, 0xCA, 0xE8, 0xD4,
  161.                                                     0x20, 0xC7, 0xE4, 0xD9, 0xD1, 0xC8, 0xEA, 0};
  162.     char *text3  = " Office AWAY.";
  163.     char *kanjiText = "&";
  164.     fixed ascent, descent;
  165.     gxPoint center;
  166.     GDHandle max;
  167.     short mbh = GetMBarHeight ();
  168.     gxGraphicsClient ourClient;
  169.     
  170.     MaxApplZone(); MoreMasters(); MoreMasters();
  171.  
  172.     ourClient = GXNewGraphicsClient(0L, 1024 * 1024, 0L);
  173.     if (ourClient != NULL) {
  174.         SetGraphicsLibraryErrors();
  175.         SetGraphicsLibraryNotices ();
  176.         /*GXSetValidation(gxInternalValidation | gxStructureValidation | gxNoMemoryManagerValidation);    ** uncomment this for less speed and more error-checking */
  177.     
  178.         InitCommonColors ();
  179.         
  180.         InitGraf(&thePort);
  181.         InitFonts();
  182.         InitWindows();
  183.         InitMenus ();
  184.         InitCursor();
  185.     
  186.         SetupMenus ();
  187.         
  188.         /* find the deepest monitor, and make a window that just covers it */
  189.         max = GetMaxDevice (&bigRect);
  190.         qdWindowRect = (**max).gdRect;
  191.         
  192.         /* bring it down one mbh for the header, maybe another if on main screen */
  193.         if (qdWindowRect.top == 0 && qdWindowRect.left == 0) qdWindowRect.top += mbh;
  194.         qdWindowRect.top += mbh;
  195.             
  196.         InsetRect (&qdWindowRect, 4, 4);
  197.         ShortRectToFixed (&qdWindowRect, &windowRect);
  198.         center.x = (windowRect.right - windowRect.left) / 2;
  199.         center.y = (windowRect.bottom - windowRect.top) / 2;
  200.             
  201.         myWindow = NewWindow(nil, &qdWindowRect, (StringPtr) "\pCircular Layout Sample",
  202.                  true, documentProc, (WindowPtr) -1L, true, 0L);
  203.         
  204.         myPort = GXNewWindowViewPort (myWindow);
  205.         SetDefaultViewPort (myPort);
  206.         GXSetViewPortDither( myPort, 4 );
  207.     
  208.         /*
  209.             When we want to erase the whole window, we just GXDrawShape (whiteOut).
  210.          */
  211.         whiteOut = GXNewShape(gxFullType);
  212.         GXSetShapeColor (whiteOut, &colorWhite);
  213.     
  214.         /* make a 270 x 270 gxRectangle centered in the window */
  215.         r.top = center.y - ff(135);
  216.         r.left = center.x - ff(135);
  217.         r.bottom = center.y + ff(135);
  218.         r.right = center.x + ff(135);
  219.         
  220.         /* use the gxRectangle to make an oval, and get it ready to be dashed */
  221.         oval = NewOval(&r);
  222.         GXSetShapeFill(oval, gxClosedFrameFill);
  223.         GXSetShapePen(oval, IntToFixed(14));
  224.         shapeColor = hsvInitial;
  225.     
  226.         /* gxInitialize the textRuns array */
  227.         textRuns[0] = text1;
  228.         textRuns[1] = text2;
  229.         textRuns[2] = text3;
  230.         
  231.         /* gxInitialize the textLengths array */
  232.         textLengths[0] = StrLength(text1);
  233.         textLengths[1] = StrLength(text2);
  234.         textLengths[2] = StrLength(text3);
  235.         
  236.         totalLength = textLengths[0] + textLengths[1] + textLengths[2];
  237.     
  238.         /* Make a default gxLayoutOptions and gxRunControls */
  239.         InitializeLayoutOptions (&gxLayoutOptions);
  240.         InitializeRunControls (&controls);
  241.         
  242.         /* run 0 is 28 pt. Helvetica */
  243.         textStyles[0] = NewLayoutStyle((char *) "\pHelvetica", ff(28), 0, &controls, nil, 0, nil);
  244.     
  245.         /* run 1 is 28 pt. Baghdad (Arabic) */
  246.         textStyles[1] = NewLayoutStyle((char *) "\pBaghdad Plain", ff(28), 0, &controls, nil, 0, nil);
  247.         
  248.         /* run 2 is 28 pt. Times Roman */
  249.         textStyles[2] = NewLayoutStyle((char *) "\pTimes Roman", ff(28), 0, &controls, nil, 0, nil);
  250.         
  251.         kanji = NewSingleLayout (
  252.             kanjiText,
  253.             (char *) "\pTimes Roman",
  254.             ff(175),
  255.             &gxLayoutOptions,
  256.             nil,
  257.             0,
  258.             &controls,
  259.             nil,
  260.             0,
  261.             nil);
  262.         GXGetLayoutSpan(kanji, &ascent, &descent);
  263.         GXGetShapeBounds(kanji, 0, &bounds);
  264.         GXMoveShapeTo (kanji, center.x - ((bounds.right - bounds.left) / 2), center.y + ((ascent - descent) / 2));
  265.     
  266.         /* make sure that kanji has a unique gxTransform, and scale it */
  267.         {    gxTransform xform = GXGetShapeTransform(kanji);
  268.             if (GXGetTransformOwners(xform) > 1)
  269.             {    xform = GXCopyToTransform(nil, xform);
  270.                 GXSetShapeTransform(kanji, xform);
  271.                 GXDisposeTransform (xform);
  272.             }
  273.         }
  274.         GXScaleTransform(GXGetShapeTransform(kanji), IntToFixed(2), f(1,0x6000), center.x, center.y);
  275.         
  276.         /* Build the layout. */
  277.         
  278.         layout = GXNewLayout(
  279.             3,
  280.             textLengths,
  281.             (void *)textRuns,
  282.             3,
  283.             textLengths,
  284.             textStyles,
  285.             1,
  286.             &totalLength,
  287.             &level0,
  288.             &gxLayoutOptions,
  289.             nil);
  290.             
  291.         (void) GXGetShapeBounds (layout, 0, &bounds);
  292.         GXSetShapeType(layout, gxPathType);
  293.         
  294.         /* now use the layout to dash the oval */
  295.         d.attributes = gxAutoAdvanceDash | gxBreakDash;
  296.         d.dash = layout;
  297.         d.phase = 0;
  298.         d.advance = bounds.right + ff(10);
  299.         d.scale = IntToFixed(14);
  300.         
  301.         /* make sure that oval has a unique gxTransform, and scale it */
  302.         {    gxTransform xform = GXGetShapeTransform(oval);
  303.             if (GXGetTransformOwners(xform) > 1)
  304.             {    xform = GXCopyToTransform(nil, xform);
  305.                 GXSetShapeTransform(oval, xform);
  306.                 GXDisposeTransform (xform);
  307.             }
  308.         }
  309.         GXScaleTransform(GXGetShapeTransform(oval), fixed1*2, f(1,0x6000), center.x, center.y);
  310.         
  311.         eraseOval = GXNewShape(gxEmptyType);
  312.         /* Now just keep re-drawing the gxShape in different colors until it's time to go */
  313.         while (!done)
  314.         {    GXSetShapeColor (oval, &shapeColor);
  315.             GXIgnoreGraphicsNotice( dash_already_set );
  316.             GXSetShapeDash (oval, &d);
  317.             GXPopGraphicsNotice();
  318.             GXCacheShape (oval);
  319.     
  320.             if (shapeColor.element.hsv.hue == 0)
  321.             {    SetShapeCommonColor (kanji, kanjiColor);
  322.                 GXCacheShape (kanji);
  323.                 if (++kanjiColor > apple_blue) kanjiColor = apple_green;
  324.                 d.phase = 0;
  325.             }
  326.             
  327.             GXDrawShape (eraseOval);
  328.             GXDrawShape (oval);
  329.             GXCopyToShape(eraseOval, oval);
  330.             GXSetShapeColor (eraseOval, &colorWhite);
  331.             GXDrawShape (kanji);
  332.             
  333.             shapeColor.element.hsv.hue += 0x10000/32;
  334.             d.phase += fract1/32;
  335.     
  336.             if (WaitNextEvent(everyEvent, &theEvent, 0, nil))
  337.             {
  338.                 switch(theEvent.what)
  339.                 {
  340.                     case mouseDown:
  341.                     switch (FindWindow(theEvent.where, &whichWindow))
  342.                     {    case inSysWindow:
  343.                             SystemClick(&theEvent, whichWindow);
  344.                             break;
  345.                         
  346.                         case inMenuBar:
  347.                             DoMenuCommand (MenuSelect (theEvent.where));
  348.                         break;
  349.                             
  350.                         case inDrag:
  351.                             DragWindow(whichWindow, theEvent.where, &screenBits.bounds);
  352.                         break;
  353.     
  354.                         case inGrow:
  355.                         {    register long newSize;
  356.     
  357.                             newSize = GrowWindow(whichWindow, theEvent.where, &growRect);
  358.                             SizeWindow(whichWindow, LoWord(newSize), HiWord(newSize), true);
  359.                         }
  360.                         break;
  361.                         
  362.                         case inGoAway:
  363.                             if (TrackGoAway(whichWindow, theEvent.where)) done = true;
  364.                         break;
  365.     
  366.                         case inContent:
  367.                             if (whichWindow != FrontWindow())
  368.                                 SelectWindow(whichWindow);
  369.                         break;
  370.                     }
  371.                     break;
  372.     
  373.                     case keyDown:
  374.                     case autoKey:
  375.                         if (myWindow == FrontWindow () && theEvent.modifiers & cmdKey)
  376.                             DoMenuCommand (MenuKey (theEvent.message & charCodeMask));
  377.                     break;
  378.     
  379.                     case updateEvt:
  380.                         BeginUpdate((WindowPtr)theEvent.message);
  381.                         GXDrawShape (whiteOut);
  382.                         GXDrawShape (oval);
  383.                         GXDrawShape (kanji);
  384.                         EndUpdate((WindowPtr)theEvent.message);
  385.                     break;
  386.                 }
  387.             }
  388.         }
  389.         /* dispose everything we've allocated. */
  390.         DisposeCommonColors ();
  391.         GXDisposeShape (oval);
  392.         GXDisposeShape (eraseOval);
  393.         GXDisposeShape(layout);
  394.         GXDisposeShape(kanji);
  395.         GXDisposeStyle (textStyles[0]); GXDisposeStyle (textStyles[1]);
  396.         GXDisposeStyle (textStyles[2]);
  397.         DisposeWindow(myWindow);
  398.         GXDisposeShape (whiteOut);
  399.         GXDisposeGraphicsClient(ourClient);
  400.     }
  401. }
  402.